home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 25 / Cream of the Crop 25.iso / bbs / doorinfo.zip / ZMRECV.C < prev    next >
C/C++ Source or Header  |  1997-05-14  |  20KB  |  950 lines

  1. /*
  2. **************************************************************************
  3. **
  4. ** Doors program to send files via zmodem
  5. **
  6. ** Compile instructions for MSC 5.1 and 6.0
  7. ** Note - structs.h hsz.h and bbscfg.h are required.
  8. **        these files, and lmtca.obj, are available in doorinfo.zip
  9. **
  10. **  cl /c /AL /Gs zmrecv.c
  11. **  link /st:4096 zmrecv lmtca fsubs;
  12. **************************************************************************
  13. */
  14.  
  15. #include "stdio.h"
  16. #include "stdlib.h"
  17. #include "string.h"
  18. #include "dos.h"
  19. #include <time.h>
  20. #include "structs.h"
  21. #include "hsz.h"
  22. #include "bbscfg.h"
  23. #include "crctab.c"
  24. #include "fossil.h"
  25. #include "c:\mt\tcb.h"
  26.  
  27. void sendzrinit(void);
  28. void sendzskip(void);
  29. void sendzrpos(void);
  30. void sendzack(void);
  31. void sendznak(void);
  32. void sendzfin(void);
  33. void sendhexhdr(char *buf, int count);
  34. int check_timer(time_t t);
  35. void bsend(char *str);
  36. int endtask(char *);
  37. void clear_queue(int q);
  38. unsigned int calccrc(char *buf, int len);
  39. unsigned long calccrc32(char *buf, int len);
  40. int getheader(void);
  41. int getdata(void);
  42. int check_crc(char *buf, int cnt);
  43.  
  44. typedef struct acct_rec acctp[];
  45. typedef struct user_rec userp[];
  46.  
  47. acctp far *acct;
  48. userp far *user;        /* pointer to an array of user_rec structures */
  49.  
  50. #define MY_buf_size 10*1024
  51. char MY_buf[MY_buf_size];
  52.  
  53. unsigned int calccrc();
  54. unsigned long int calccrc32();
  55.  
  56. time_t t;
  57.  
  58. char outbuf[40];
  59.  
  60. int zdle_hit;
  61.  
  62.  
  63. char buffer[1100];
  64. char hdrbuf[2200];
  65. char holdbuf[1200];
  66. int holdidx, holdcnt;
  67.  
  68. char path[60];
  69.  
  70. unsigned long filepos;
  71.  
  72. int crc32 = 0;            /* use 16 or 32 bit crc */
  73.  
  74. int recvmode;            /* used to determine how much of header
  75.                  * received */
  76. int hdrincnt;            /* must receive 13 bytes */
  77.  /* type, 8 bytes of flags, 4 bytes of crc, in ascii hex */
  78.  
  79. struct msg1
  80. {                /* used for text in/out */
  81.     int m1typ;
  82.     int m1num;            /* line number */
  83.     char m1text[1000];
  84. }  *m1;
  85.  
  86. struct msg3
  87. {                /* the initial message with line num and
  88.                  * queue nums */
  89.     int m3typ;            /* must be 7 */
  90.     int m3line;
  91.     int m3inq;
  92.     int m3outq;
  93.     void far *acctptr;
  94.     void far *userptr;
  95.     int maxline;
  96.     struct cfg_rec far *cfgptr;    /* pointer to BBSCFG record */
  97. }  *m3;
  98.  
  99.  
  100. int who;
  101. int inq, outq;
  102.  
  103. FILE *fp;
  104.  
  105. int single_file_mode = 0;
  106.  
  107. main(int argc, char *argv[])
  108. {
  109.     int file_status;
  110.     int k, n;
  111.     int n1;
  112.     unsigned long lj;
  113.     int errorcount;
  114.  
  115.     fp = NULL;
  116.  
  117.     m1 = (struct msg1 *) buffer;
  118.     m3 = (struct msg3 *) buffer;
  119.  
  120. /*
  121. ** wait for the initialization event from FALKEN.
  122. ** it will be event type 7.
  123. ** If for some reason we get an event type 8, we must terminate.
  124. */
  125.     time(&t);
  126.     m3->m3typ = 0;
  127.     while (m3->m3typ != 7)
  128.     {
  129.     if (testmsg(1))
  130.     {
  131.         recvmsg(1, buffer, 1000);
  132.         if (m3->m3typ == 8)
  133.         endtask("[init] abort message received");
  134.     }
  135.     if (check_timer(t) > 20)
  136.         endtask("timeout waiting for init event");
  137.     relinq();
  138.     }
  139.  
  140.     acct = m3->acctptr;
  141.     user = m3->userptr;
  142.  
  143. /*
  144. ** get the input and output queue numbers we have been assigned,
  145. ** and which line this user is logged on to.
  146. */
  147.  
  148.     inq = m3->m3inq;
  149.     outq = m3->m3outq;
  150.     who = m3->m3line;
  151. /*
  152. ** Set line up for 8 bits, no parity, no matter what the original
  153. ** settings are for!
  154. */
  155.  
  156.     holdidx = holdcnt = 0;
  157.  
  158.     (*user)[who].u_timeroff = 1;   /* turn off timer during upload */
  159. /*
  160. **  Now the main loop -
  161. */
  162.  
  163.     setpri(2);
  164.  
  165.     if (argc > 1)
  166.     {
  167.     strcpy(path, argv[1]);
  168.     if (path[0] == '-' && path[1] == 'p')
  169.     {
  170.         if (path[2])
  171.         {
  172.         strcpy(path, &argv[1][2]);    /* skip the -p */
  173.         }
  174.         else
  175.         {
  176.         if (argc > 2)
  177.         {
  178.             strcpy(path, argv[2]);
  179.         }
  180.         else
  181.         {
  182.             path[0] = '\0';
  183.         }
  184.         }
  185.     }
  186.     else
  187.     {
  188.         single_file_mode = 1;
  189.     }
  190.     clear_queue(inq);
  191.     }
  192.     else
  193.     {
  194. /*
  195. ** wait for the text message with filenames
  196. */
  197.     time(&t);        /* get timer base value */
  198.     for (;;)
  199.     {
  200.         if (testmsg(inq))
  201.         {
  202.         recvmsg(inq, buffer, 1000);
  203.         if (m1->m1typ == 8)
  204.             endtask("[path] abort message received");
  205.         else if (m1->m1typ == 1)
  206.         {
  207.             if (strncmp(m1->m1text, "path=", 5) == 0)
  208.             {
  209.             strcpy(path, m1->m1text + 5);
  210.             break;
  211.             }
  212.         }
  213.         }
  214.         if (check_timer(t) > 20)
  215.         endtask("timeout waiting for path= message");
  216.         delay(1);
  217.     }
  218.     }
  219.  
  220.     m1->m1typ = 8;        /* get control of the line */
  221.     send_md_msg(outq, buffer, 2);
  222.  
  223.     delay(1);
  224.  
  225.     bsend("Zmodem Batch file upload activated.\r\n");
  226.     bsend("Start your Zmodem transfer now....\r\n");
  227.  
  228. /*
  229. ** Now we have to establish the zmodem dialogue.  We are the receiver,
  230. ** so we have to send ZRINIT packets to the receiver telling him we
  231. ** are ready to go!
  232. ** Meantime, the sender is sending ZRQINIT packets.
  233. **
  234. */
  235.  
  236.     holdcnt = holdidx = 0;
  237.  
  238.     for (;;)            /* loop forever, waiting for zfin */
  239.     {
  240.     n = 0;            /* ZSINIT or ZFILE not received yet */
  241.     errorcount = 0;        /* how many ZRQINIT packets have we sent ? */
  242.     sendzrinit();        /* send the first zrinit packet */
  243.     file_status = 0;    /* waiting for zsinit */
  244.     while (n == 0)
  245.     {
  246.         if (k = getheader())/* see if we got a header in */
  247.         {
  248.         switch (k)
  249.         {
  250.             case 1:    /* hex packet received */
  251.             case 4:    /* binary-16 */
  252.             case 5:    /* binary 32 */
  253.             switch (hdrbuf[0])
  254.             {
  255.                 case ZRQINIT:
  256.                 sendzrinit();
  257.                 break;
  258.                 case ZSINIT:
  259. /*
  260. ** Only controls possible are for escaping control characters, and
  261. ** since we are sending only HEX headers, we don;t need to do that.
  262. ** So we just ignore any control bites set in the flags
  263. */
  264.                 file_status = 1;    /* waiting for file info */
  265.                 filepos = 0L;
  266.                 sendzack();
  267.                 break;
  268.                 case ZFIN:
  269.                 sendzfin();
  270.                 delay(1);
  271.                 endtask("ZFIN received");
  272.                 break;
  273.                 case ZABORT:
  274.                 sendzfin();
  275.                 delay(1);
  276.                 endtask("ZABORT received");
  277.                 break;
  278.                 case ZFERR:
  279.                 sendzfin();
  280.                 delay(1);
  281.                 endtask("ZFERR received");
  282.                 break;
  283.                 case ZFILE:
  284. /*
  285. ** A word of warning -
  286. ** We do no conversion, compression, or file management.
  287. ** We assume that if a file exists, the user is completing an
  288. ** aborted download
  289. **
  290. ** Call getdata() which will return the entire data buffer received,
  291. ** including the crc bytes.  All escape encoding will have been removed,
  292. ** and it contains pure binary data - in this case, the file name to
  293. ** receive.
  294. */
  295.                 n1 = getdata();
  296.  
  297.                 if (n1 == 203)
  298.                 {
  299.                     sendzrinit();
  300.                     break;
  301.                 }
  302.                 if (check_crc(hdrbuf, hdrincnt - (crc32 ? 4 : 2)) == 1)
  303.                 {
  304.                     sendznak();
  305.                     break;
  306.                 }
  307. /*
  308. ** Data is good, and it is the ZCRCW packet we were expecting.
  309. ** See if the file exists, and if so, set filepos to the end of file.
  310. ** If we received the file name on the command line, just use it.
  311. **
  312. ** If we already got the one file we were expecting,
  313. ** then skip this file.
  314. */
  315.  
  316.                 if (single_file_mode == 2)
  317.                 {
  318.                     sendzskip();
  319.                     break;
  320.                 }
  321.                 strcpy(buffer, path);
  322.                 if (!single_file_mode)
  323.                 {
  324.                     strcat(buffer, hdrbuf);
  325.                 }
  326.                 fp = fopen(buffer, "ab");
  327.                 if (fp == NULL)
  328.                 {
  329.                     sendzskip();    /* cannot open file! */
  330.                     break;
  331.                 }
  332.                 else
  333.                 {
  334.                     setvbuf(fp, MY_buf, _IOFBF, MY_buf_size);
  335.                     if (fseek(fp, 0L, SEEK_END) != 0)    /* go to end of file */
  336.                     fseek(fp, 0L, SEEK_SET);    /* if err, goto start */
  337.                     filepos = ftell(fp);
  338.                     sendzrpos();    /* ack with offset */
  339.                     file_status = 2;
  340.                     if (single_file_mode)
  341.                     single_file_mode = 2;
  342.                 }
  343.                 break;
  344.                 case ZDATA:    /* a data packet */
  345.                 memcpy((void *) &lj, &hdrbuf[1], 4);
  346.                 if (check_crc(hdrbuf, hdrincnt - (crc32 ? 4 : 2)) == 1)
  347.                 {
  348.                     sendznak();
  349.                     break;
  350.                 }
  351.                 else if (lj != filepos)
  352.                 {
  353.                     sendzrpos();
  354.                     break;
  355.                 }
  356.                 else
  357.                 {
  358.                 getmoredata:
  359.                     n1 = getdata();
  360.                     if (n1 == 203)
  361.                     {
  362.                     sendzrpos();
  363.                     }
  364.                     else
  365.                     {
  366.                     if (check_crc(hdrbuf, hdrincnt - (crc32 ? 4 : 2)) == 1)
  367.                     {
  368.                         sendzrpos();
  369.                         break;
  370.                     }
  371. /*
  372. ** got good data, so we will append to the file.
  373. */
  374.                     if (fp != NULL)
  375.                     {
  376.                         fwrite(hdrbuf, 1, hdrincnt - (crc32 ? 5 : 3), fp);
  377.                         filepos = ftell(fp);
  378.                     }
  379.                     switch (n1)
  380.                     {
  381.                         case ZCRCW:
  382.                         sendzack();
  383.                         break;
  384.                         case ZCRCE:
  385.                         sendzrpos();
  386.                         break;
  387.                         case ZCRCG:
  388.                         goto getmoredata;
  389.                         break;
  390.                         case ZCRCQ:
  391.                         sendzack();
  392.                         goto getmoredata;
  393.                         break;
  394.                     }
  395.                     }
  396.                 }
  397.                 break;
  398.                 case ZEOF:    /* end of file */
  399.                 if (check_crc(hdrbuf, hdrincnt - (crc32 ? 4 : 2)) == 1)
  400.                 {
  401.                     sendznak();
  402.                     break;
  403.                 }
  404.                 memcpy((void *) &lj, &hdrbuf[1], 4);
  405.                 if (lj == filepos)    /* this is real eof */
  406.                 {
  407.                                     (*acct)[who].uploads++;
  408.                                     (*acct)[who].upload_k += (filepos + 1023L) / 1024L;
  409.                     if (fp != NULL)
  410.                     fclose(fp);
  411.                     fp = NULL;
  412.                     filepos = 0L;
  413.                     n = 1;    /* send a zrinit */
  414.                 }    /* if not real end of file, ignore
  415.                      * header */
  416.             }    /* end inner switch (hdrbuf[0]) */
  417.             break;
  418.             case 203:    /* timeout */
  419.             if (++errorcount > 20)
  420.                 endtask("errorcount > 20");    /* waited too long for
  421.                              * zrinit */
  422.             if (file_status == 2)
  423.             {
  424.                 sendzrpos();
  425.             }
  426.             else
  427.             {
  428.                 sendzrinit();
  429.             }
  430.             break;
  431.         }
  432.         }            /* end if getheader */
  433.     }            /* end while n == 0 */
  434.     }                /* end for (;;) */
  435. }
  436.  
  437.  
  438. void sendzrinit()
  439. {
  440.     int j;
  441.     char buf[20];
  442.     buf[0] = ZRINIT;        /* type */
  443.     for (j = 1; j < 5; j++)
  444.     buf[j] = 0;        /* set flags to 0 */
  445.     buf[1 + ZF0] = CANFDX | CANOVIO | CANBRK | CANFC32;
  446.     buf[1 + ZP1] = 2;        /* 0x400 = 1024 byte input buffer */
  447.     buf[1 + ZP1] = 0;        /* 0x400 = 1024 byte input buffer */
  448.     sendhexhdr(buf, 5);
  449. }
  450.  
  451.  
  452. void sendzskip()
  453. {
  454.     int j;
  455.     char buf[20];
  456.     buf[0] = ZSKIP;        /* type */
  457.     for (j = 1; j < 5; j++)
  458.     buf[j] = 0;        /* set flags to 0 */
  459.     sendhexhdr(buf, 5);
  460. }
  461.  
  462. void sendzrpos()
  463. {
  464.     unsigned char buf[20];
  465.     buf[0] = ZRPOS;        /* type */
  466.     memcpy(&buf[1], (void *) &filepos, 4);
  467.     sendhexhdr(buf, 5);
  468. }
  469.  
  470. void sendzack()
  471. {
  472.     unsigned char buf[20];
  473.     buf[0] = ZACK;        /* type */
  474.     memcpy(&buf[1], (void *) &filepos, 4);
  475.     sendhexhdr(buf, 5);
  476. }
  477.  
  478. void sendznak()
  479. {
  480.     unsigned char buf[20];
  481.     buf[0] = ZNAK;        /* type */
  482.     memcpy(&buf[1], (void *) &filepos, 4);
  483.     sendhexhdr(buf, 5);
  484. }
  485.  
  486. /*
  487. ** Utility routines follow
  488. **
  489. ** These routines call Multidos interface routines which are available
  490. ** with the FALKEN  Doors development kit.
  491. **
  492. ** See the file MDOS.TXT for a description of the interface routines.
  493. */
  494.  
  495. void sendzfin()
  496. {
  497.     int j;
  498.     char buf[8];
  499.  
  500.     buf[0] = ZFIN;        /* type */
  501.     for (j = 1; j < 5; j++)
  502.     buf[j] = 0;        /* set flags to 0 */
  503.     sendhexhdr(buf, 5);
  504. }
  505.  
  506. void sendhexhdr(buf, count)
  507. char *buf;
  508. int count;
  509. {
  510.     int j, k;
  511.     unsigned int c;
  512.     char w[6];
  513.  
  514.     j = k = 0;
  515.     c = calccrc(buf, count);    /* calccrc returns new buffer length */
  516.  
  517.     buf[count++] = 0xff & (c >> 8);
  518.     buf[count++] = 0xff & c;
  519.     j = 0;
  520.     outbuf[j++] = ZPAD;
  521.     outbuf[j++] = ZPAD;
  522.     outbuf[j++] = ZDLE;
  523.     outbuf[j++] = 'B';        /* send hex header! */
  524.     for (k = 0; k < count; k++)
  525.     {
  526.     sprintf(w, "%2.2x", (int) (0xff & buf[k]));
  527.     outbuf[j++] = w[0];
  528.     outbuf[j++] = w[1];
  529.     }
  530.     outbuf[j++] = '\r';
  531.     outbuf[j++] = '\n';
  532.     outbuf[j++] = 17;        /* x-on */
  533.  
  534.     f_send(who, outbuf, j);
  535. }
  536.  
  537. int check_timer(t)
  538. time_t t;
  539. {
  540.     time_t cur_time;
  541.     time(&cur_time);
  542.     return (int) (cur_time - t);
  543. }
  544.  
  545.  
  546.  
  547. /*
  548. ** Send a null terminated string to FALKEN, to be transmitted to
  549. ** a particular line;
  550. */
  551.  
  552. void bsend(str)
  553. char *str;
  554. {
  555.     f_send(who, str, strlen(str));
  556. }
  557.  
  558. /*
  559. ** wait for a message on the input queue named.
  560. ** if no message, relinquish our time slice.
  561. ** after all, no need to just loop here when other tasks
  562. ** can use the processor.
  563. */
  564.  
  565. /*
  566. ** This program gracefully exits by
  567. ** sending the 'task has terminated' message to FALKEN,
  568. ** then terminating.
  569. */
  570. int endtask(char *msg)
  571. {
  572.     char b[120];
  573. /*
  574. ** Put line parameters back the way they were
  575. */
  576.  
  577.     sprintf(b, "ZMRECV : %s", msg);
  578.     bbslog(b);
  579.     if (fp != NULL)
  580.     fclose(fp);
  581.     (*user)[who].u_timeroff = 0;   /* turn off back on */
  582.     exit(0);
  583. }
  584.  
  585.  
  586. void clear_queue(q)
  587. int q;
  588. {
  589.     while (testmsg(q) > 0)
  590.     recvmsg(q, buffer, 1024);
  591. }
  592.  
  593.  
  594. unsigned int calccrc(buf, len)
  595. char *buf;
  596. int len;
  597. {
  598.     unsigned int c;
  599.     c = 0;
  600.     while (len--)
  601.     c = updcrc((0xff & *buf++), c);
  602.     c = updcrc(0, c);
  603.     c = updcrc(0, c);
  604.     return c;            /* returns length of buffer, counting crc */
  605. }
  606.  
  607. unsigned long calccrc32(buf, len)
  608. char *buf;
  609. int len;
  610. {
  611.     unsigned long int c;
  612.     c = 0xffffffffL;
  613.     while (len--)
  614.     {
  615.     c = UPDC32((0xff & *buf++), c);
  616.     }
  617.     c = ~c;
  618.     return c;            /* returns length of buffer, counting crc */
  619. }
  620.  
  621. getheader()
  622. {
  623.     int j, k, m, n;
  624.     int cancount;
  625.     int bytes_expected;
  626.  
  627.     n = 0;
  628.  
  629.     cancount = 0;
  630.     recvmode = 0;
  631.     hdrincnt = 0;
  632.     for (;;)
  633.     {
  634.     time(&t);        /* wait 20 seconds to receive a header */
  635.     while (holdcnt == holdidx)
  636.     {
  637.         holdidx = 0;
  638.         if ((holdcnt = f_recv(who, holdbuf, 1024)) == 0)    /* nothing in */
  639.         {
  640.         if (check_timer(t) > 5)
  641.         {
  642.             return 203;
  643.         }
  644.         if (testmsg(inq))
  645.         {
  646.             recvmsg(inq, buffer, 200);
  647.             if (m1->m1typ == 8)
  648.             endtask("[getheader] abort message received");
  649.         }
  650.         relinq();
  651.         }
  652.     }
  653.     time(&t);
  654.     while (holdcnt > holdidx)    /* got some data waiting */
  655.     {
  656.         k = holdbuf[holdidx++];
  657.         if (k == ZDLE)
  658.         {
  659.         if (++cancount >= 4)
  660.             endtask("[getheader] CAN received.");
  661.         }
  662.         else
  663.         cancount = 0;
  664.         switch (recvmode)
  665.         {
  666.         case 0:    /* waiting for zpad */
  667.             if (k == ZPAD)
  668.             {
  669.             recvmode = 1;    /* got header, looking for ZDLE */
  670.             /* not gonna get zdle, get B */
  671.             }
  672. /*
  673. ** Got zpad.  If next byte not zpad or zdle, start looking for zpad again
  674. ** if zpad, continue looking for zdle.
  675. ** if zdle, look for header type
  676. */
  677.             break;
  678.         case 1:    /* got zpad, looking for zdle */
  679.             if (k == ZPAD)
  680.             break;    /* ignore duplicate zpad */
  681.             else if (k == ZDLE)
  682.             {
  683.             recvmode = 2;
  684.             hdrincnt = 0;
  685.             }
  686. /*
  687. ** we must get the 'B' next if this is a ZDLE
  688. ** we may get the 'B' without a ZDLE. This is OK, we just start
  689. ** accumulating the header
  690. */
  691.             else if (k == 'B')
  692.             {
  693.             recvmode = 3;    /* hex header */
  694.             crc32 = 0;
  695.             }
  696.             else
  697.             {
  698.             recvmode = 0;    /* not one of these - error */
  699.             }
  700.             break;
  701.         case 2:    /* got zdle - look for header type. */
  702.             if (k == 'B')
  703.             {
  704.             recvmode = 3;    /* hex header */
  705.             crc32 = 0;
  706.             }
  707.             else if (k == 'A')    /* 16 bit CRC binary header */
  708.             {
  709.             recvmode = 4;
  710.             crc32 = 0;
  711.             bytes_expected = 7;
  712.             }
  713.             else if (k == 'C')    /* 32 bit CRC binary header */
  714.             {
  715.             recvmode = 5;
  716.             crc32 = 1;
  717.             bytes_expected = 9;
  718.             }
  719.             else
  720.             {
  721.             recvmode = 0;    /* wait for pad */
  722.             holdidx--;    /* reprocess this char */
  723.             }
  724.             break;
  725. /*
  726. ** we are now receiving the data packet from the receiver.
  727. ** if it is a hex header, and will be exactly 17 bytes long.
  728. **  Type(2) plus 4 flags(8) plus 2 CRC bytes(4) plus cr/lf/xon = 17
  729. **    hex encoding, of course
  730. **
  731. ** if we get a bad character in, go back to waiting for ZPAD
  732. */
  733.         case 3:    /* now assemble hex packet */
  734.             if ((k != 17) && (k != 19))
  735.             hdrbuf[hdrincnt++] = k;
  736.             if ((hdrincnt > 13) && ((0x7f & k) == 10))    /* look for LF */
  737.             {
  738.             for (j = k = 0; j < 7; j++)
  739.             {
  740.                 n = hdrbuf[k++];
  741.                 n = tolower(n);
  742.                 if (n <= '9')
  743.                 n -= '0';
  744.                 else
  745.                 n = (n - 'a') + 10;
  746.                 m = hdrbuf[k++];
  747.                 m = tolower(m);
  748.                 if (m <= '9')
  749.                 m -= '0';
  750.                 else
  751.                 m = (m - 'a') + 10;
  752.                 hdrbuf[j] = n * 16 + m;
  753.             }
  754.             recvmode = 0;
  755.             return 1;    /* show we got a header */
  756.             }
  757.             break;
  758.         case 4:    /* binary header */
  759.         case 5:    /* crc-32 header */
  760.             if ((k == 17) || (k == 19))
  761.             break;    /* ignore these chars */
  762.             if (zdle_hit)
  763.             {
  764.             switch (k)
  765.             {
  766.                 case 'l':
  767.                 hdrbuf[hdrincnt++] = 0x7f;
  768.                 break;
  769.                 case 'm':
  770.                 hdrbuf[hdrincnt++] = 0xff;
  771.                 break;
  772.                 case ZDLEE:
  773.                 hdrbuf[hdrincnt++] = ZDLE;
  774.                 break;
  775.                 default:
  776.                 hdrbuf[hdrincnt++] = k ^ 0x40;
  777.                 break;
  778.             }
  779.             zdle_hit = 0;
  780.             }
  781.             else    /* zdle_hit == 0 */
  782.             {
  783.             if (k == ZDLE)
  784.                 zdle_hit = 1;
  785.             else
  786.                 hdrbuf[hdrincnt++] = k;
  787.             }
  788.             if (hdrincnt == bytes_expected)
  789.             {
  790.             return recvmode;    /* 4 or 5  = bin header */
  791.             }
  792.             break;
  793.         }            /* end switch */
  794.     }            /* end while holdcnt != holdidx */
  795.     }                /* end for ever */
  796. /*
  797. ** We will NEVER get here.
  798. ** All returns are from within the FOR(;;) statement
  799. */
  800. }
  801.  
  802. /*
  803. ** Getdata is called after receiving a ZSINIT, ZFILE, or ZDATA packet.
  804. ** We will set a long timer - like 20 seconds.
  805. ** We will accumulate data until we find one of :
  806. **   ZCRCG, ZCRCW, ZCRCE, ZCRCQ, and return it as the type.
  807. */
  808.  
  809. getdata()
  810. {
  811.     int k;
  812.     int rcrc;
  813.     int cancount;
  814.     int rtrn;
  815.  
  816.     rcrc = 0;            /* will be set to non-zero when getting crc */
  817.     cancount = 0;
  818.     hdrincnt = 0;        /* will be input char count */
  819.     zdle_hit = 0;
  820.     for (;;)
  821.     {
  822.     time(&t);        /* wait 20 seconds to receive a header */
  823.     while (holdcnt == holdidx)
  824.     {
  825.         holdidx = 0;
  826.         if ((holdcnt = f_recv(who, holdbuf, 1024)) == 0)    /* nothing in */
  827.         {
  828.         if (check_timer(t) > 5)
  829.             return 203;
  830.         if (testmsg(inq))
  831.         {
  832.             recvmsg(inq, buffer, 200);
  833.             if (m1->m1typ == 8)
  834.             endtask("[getdata] abort message received");
  835.         }
  836.         relinq();
  837.         }
  838.     }
  839.     time(&t);
  840.     while (holdcnt != holdidx)
  841.     {
  842.         if (hdrincnt > 2180)
  843.         return 203;    /* too big!  return general timeout error */
  844.  
  845.         k = holdbuf[holdidx++];
  846. /* if over 1040 bytes in receive buffer, error. return and nak */
  847.         if ((k == 17) || (k == 19))
  848.         continue;    /* ignore these chars */
  849.  
  850.         if (k == ZDLE)
  851.         {
  852.         if (++cancount > 4)
  853.             endtask("[getdata] CAN received");
  854.         }
  855.         else
  856.         cancount = 0;
  857.         if (zdle_hit)
  858.         {
  859.         switch (k)
  860.         {
  861.             case 'l':
  862.             hdrbuf[hdrincnt++] = 0x7f;
  863.             break;
  864.             case 'm':
  865.             hdrbuf[hdrincnt++] = 0xff;
  866.             break;
  867.             case ZDLEE:
  868.             hdrbuf[hdrincnt++] = ZDLE;
  869.             break;
  870.             case ZCRCG:
  871.             case ZCRCE:
  872.             case ZCRCW:
  873.             case ZCRCQ:
  874.             rcrc = crc32 ? 5 : 3;    /* either 3 or 5 bytes */
  875.             rtrn = k;
  876.             hdrbuf[hdrincnt++] = k;
  877.             break;
  878.             default:
  879.             hdrbuf[hdrincnt++] = k ^ 0x40;
  880.             break;
  881.         }
  882.         zdle_hit = 0;
  883.         if (rcrc)
  884.         {
  885.             if (--rcrc == 0)
  886.             {
  887.             return rtrn;
  888.             }
  889.         }
  890.         }
  891.         else if (k == ZDLE)    /* zdle_hit == 0, and k==ZDLE */
  892.         {
  893.         zdle_hit = 1;
  894.         }
  895.         else        /* zdle_hit==0, and k!=zdle */
  896.         {
  897.         hdrbuf[hdrincnt++] = k;
  898.         if (rcrc)    /* if waiting for crc to complete */
  899.         {
  900.             rcrc--;
  901.             if (rcrc == 0)
  902.             {
  903.             return rtrn;
  904.             }
  905.         }
  906.         }            /* end else */
  907.     }            /* end while holdcnt != holdidx  */
  908.     }                /* end for (;;) */
  909. }
  910.  
  911. check_crc(buf, cnt)
  912. char *buf;
  913. int cnt;
  914. {
  915.     unsigned long uc;
  916.     unsigned c;
  917.     char *cp;
  918.     char *cp2;
  919.  
  920.     if (crc32)
  921.     {
  922.     cp = buf + cnt;
  923.     cp2 = (char *) &uc;
  924.     cp2[0] = cp[0];
  925.     cp2[1] = cp[1];
  926.     cp2[2] = cp[2];
  927.     cp2[3] = cp[3];
  928.     if (uc != calccrc32(buf, cnt))
  929.         return 1;
  930.     else
  931.         return 0;
  932.     }
  933.     else
  934.     {
  935.     cp = buf + cnt;
  936.     cp2 = (char *) &c;
  937.     cp2[1] = cp[0];
  938.     cp2[0] = cp[1];
  939.     if (c != calccrc(buf, cnt))
  940.     {
  941.         return 1;
  942.     }
  943.     else
  944.     {
  945.         return 0;
  946.     }
  947.     }
  948. }
  949.  
  950.